﻿using System;
using System.Collections.Generic;

using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace CSharpLogitechLcd
{
    /// <summary>
    /// Logique d'interaction pour MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        LogitechLCDWrapper.LCDScreen wrapper;

        public MainWindow()
        {
            InitializeComponent();
            List<LogitechLCDWrapper.LCDType> lcdTypes = new List<LogitechLCDWrapper.LCDType>((LogitechLCDWrapper.LCDType[])Enum.GetValues(typeof(LogitechLCDWrapper.LCDType)));

            cbxLcdType.DataContext = lcdTypes;
            cbxLcdType.SelectedIndex = 0;
            cbxFontSelection.DataContext = System.Drawing.FontFamily.Families;
            cbxFontSelection.SelectedIndex = 0;

            cbxFontSelectionColor.DataContext = System.Drawing.FontFamily.Families;
            cbxFontSelectionColor.SelectedIndex = 0;


            for (int i = 0; i < 8; i++)
            {
                cbxLineToDisplayText.Items.Add(i);
            }
            cbxLineToDisplayText.SelectedIndex = 0;

            Type colors = typeof(System.Drawing.Color);

            var props = colors.GetProperties(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
            cbxTextColor.DataContext = props;
            cbxTextColor.SelectedIndex = 1;


            timer = new Timer(new TimerCallback(timer_Elapsed));
            timer.Change(System.Threading.Timeout.Infinite, 100 / 6);

        }

        private void btnInitLcd_Click(object sender, RoutedEventArgs e)
        {
            if (wrapper != null)
            {
                wrapper.Dispose();
            }
            if ((LogitechLCDWrapper.LCDType)cbxLcdType.SelectedItem == LogitechLCDWrapper.LCDType.Mono)
            {
                wrapper = new LogitechLCDWrapper.MonoLCDScreen("test MONO");
                tabItemMono.IsEnabled = true;
                tabItemColor.IsEnabled = false;
            }
            if ((LogitechLCDWrapper.LCDType)cbxLcdType.SelectedItem == LogitechLCDWrapper.LCDType.Color)
            {
                wrapper = new LogitechLCDWrapper.ColorLCDScreen("test COLOR");
                tabItemColor.IsEnabled = true;
                tabItemMono.IsEnabled = false;
            }

            wrapper.EnableTextScrolling = true;
            wrapper.ScrollSpeed = 0.5;
            wrapper.LCDButtonDown += wrapper_LCDButtonPressed;
            wrapper.ButtonClicked += wrapper_ButtonClicked;
        }

        void wrapper_ButtonClicked(object sender, LogitechLCDWrapper.LCDButtonsClickedEventArgs e)
        {
            MessageBox.Show(string.Format("button {0} clicked", e.Button));
        }
        void wrapper_LCDButtonPressed(object sender, LogitechLCDWrapper.LCDButtonsDownEventArgs e)
        {
            var btns = Enum.GetValues(typeof(LogitechLCDWrapper.LCDButtons));

            foreach (LogitechLCDWrapper.LCDButtons btn in btns)
            {
                if ((e.ButtonsPressed & btn) == btn)
                {
                    switch (btn)
                    {
                        case LogitechLCDWrapper.LCDButtons.None:
                            btn1.IsChecked =
                            btn2.IsChecked =
                            btn3.IsChecked =
                            btn4.IsChecked =
                            btnUp.IsChecked =
                            btnDown.IsChecked =
                            btnLeft.IsChecked =
                            btnRight.IsChecked =
                            btnOk.IsChecked =
                            btnMenu.IsChecked =
                            btnCancel.IsChecked = false;
                            break;
                        case LogitechLCDWrapper.LCDButtons.MonoButton1:
                            btn1.IsChecked = true;
                            break;
                        case LogitechLCDWrapper.LCDButtons.MonoButton2:
                            btn2.IsChecked = true;
                            break;
                        case LogitechLCDWrapper.LCDButtons.MonoButton3:
                            btn3.IsChecked = true;
                            break;
                        case LogitechLCDWrapper.LCDButtons.MonoButton4:
                            btn4.IsChecked = true;
                            break;
                        case LogitechLCDWrapper.LCDButtons.ColorUp:
                            btnUp.IsChecked = true;
                            break;
                        case LogitechLCDWrapper.LCDButtons.ColorDown:
                            btnDown.IsChecked = true;
                            break;
                        case LogitechLCDWrapper.LCDButtons.ColorLeft:
                            btnLeft.IsChecked = true;
                            break;
                        case LogitechLCDWrapper.LCDButtons.ColorRight:
                            btnRight.IsChecked = true;
                            break;
                        case LogitechLCDWrapper.LCDButtons.ColorOk:
                            btnOk.IsChecked = true;
                            break;
                        case LogitechLCDWrapper.LCDButtons.ColorCancel:
                            btnCancel.IsChecked = true;
                            break;
                        case LogitechLCDWrapper.LCDButtons.ColorMenu:
                            btnMenu.IsChecked = true;
                            break;
                        default:
                            break;
                    }
                }
            }
        }

        private void btnShutdownLcd_Click(object sender, RoutedEventArgs e)
        {
            if (wrapper != null)
            {
                wrapper.Dispose();
                tabItemColor.IsEnabled = tabItemMono.IsEnabled = false;
            }
        }

        private void tbxTextToDisplay_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox tbx = (TextBox)sender;
            if (wrapper != null && wrapper is LogitechLCDWrapper.MonoLCDScreen)
            {
                ((LogitechLCDWrapper.MonoLCDScreen)wrapper).DisplayText(tbx.Text, Convert.ToInt32(tbx.Tag));
            }
            else if (wrapper != null)
            {
                var col = System.Drawing.Color.FromName(((System.Reflection.PropertyInfo)cbxTextColor.SelectedItem).Name);
                ((LogitechLCDWrapper.ColorLCDScreen)wrapper).Pen = new System.Drawing.Pen(col);
                ((LogitechLCDWrapper.ColorLCDScreen)wrapper).DisplayText(tbx.Text, (int) cbxLineToDisplayText.SelectedItem);
            }
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (wrapper != null)
            {
                wrapper.Dispose();
            }
        }

        #region Demo mouse move on screen
        Point previousMousePos = new Point();
        private void screenRectangle_MouseMove(object sender, MouseEventArgs e)
        {
            Point mousePos = e.GetPosition(screenRectangle);
            Rect rect = new Rect(mousePos, new Size(4, 4));
            Rect previousRect = new Rect(previousMousePos, new Size(4, 4));

            System.Drawing.Bitmap curs = Properties.Resources.cursor;

            if (wrapper != null && wrapper is LogitechLCDWrapper.MonoLCDScreen)
            {
                if (curs != null)
                {
                    System.Drawing.Bitmap erase = new System.Drawing.Bitmap(curs.Width, curs.Height);
                    for (int i = 0; i < curs.Height; i++)
                    {
                        for (int j = 0; j < curs.Width; j++)
                        {
                            erase.SetPixel(j, i, System.Drawing.Color.White);
                        }
                    }


                    wrapper.BeginDrawing();
                    ((LogitechLCDWrapper.MonoLCDScreen)wrapper).GraphicDevice.DrawImage(erase, (int)previousMousePos.X, (int)previousMousePos.Y);
                    ((LogitechLCDWrapper.MonoLCDScreen)wrapper).GraphicDevice.DrawImage(curs, (int)mousePos.X, (int)mousePos.Y);
                    wrapper.EndDrawing();
                }
                else
                {
                    for (int x = 0; x < rect.Width; x++)
                    {
                        for (int y = 0; y < rect.Height; y++)
                        {
                            ((LogitechLCDWrapper.MonoLCDScreen)wrapper).SetPixel(previousRect.Left + x, previousRect.Top + y, false);
                            ((LogitechLCDWrapper.MonoLCDScreen)wrapper).SetPixel(rect.Left + x, rect.Top + y, true);
                        }
                    }
                }
            }
            previousMousePos = mousePos;
        }
        #endregion

        #region Fonctions de démo
        bool textDemo = false;
        bool timerRunning = false;
        Timer timer;
        void timer_Elapsed(object sender)
        {
            if (textDemo)
            {
                MonoTextDemo();
            }
            else
            {
                MonoBackgroundTest();
            }
        }
        private void StartStopTimer()
        {
            timer.Change(timerRunning ? System.Threading.Timeout.Infinite : 0, 100 / 6);
            timerRunning = !timerRunning;
        }
        
        private void btnDemo_Click(object sender, RoutedEventArgs e)
        {
            backgroundIndex = 0;
            runningDot = 0;
            textDemo = false;
            StartStopTimer();
        }
        private void btnDemoText_Click(object sender, RoutedEventArgs e)
        {
            textDemo = true;
            StartStopTimer();
        }

        #region Background demo
        int backgroundIndex = 0;
        int runningDot = 0;
        TimeSpan elapsed = TimeSpan.FromSeconds(0);
        int timerTick = 0;
        private void MonoBackgroundTest()
        {
            System.Drawing.Bitmap bkg = new System.Drawing.Bitmap(wrapper.ScreenWidth, wrapper.ScreenHeight);
            timerTick++;
            switch (backgroundIndex % 6)
            {
                case 0:
                    bkg = MonoBackgroundTest1();
                    break;
                case 1:
                    bkg = MonoBackgroundTest2();
                    break;
                case 2:
                    bkg = MonoBackgroundTest3();
                    break;
                case 3:
                    bkg = MonoBackgroundTest4();
                    break;
                case 4:
                    bkg = MonoBackgroundTest5();
                    break;
                case 5:
                    bkg = MonoBackgroundTest6();
                    break;
                default:
                    bkg = MonoBackgroundTest1();
                    break;
            }
            wrapper.BeginDrawing();
            wrapper.GraphicDevice.DrawImage(bkg,0,0);
            wrapper.EndDrawing();
        }

        private System.Drawing.Bitmap MonoBackgroundTest1()
        {
            System.Drawing.Bitmap bkg = new System.Drawing.Bitmap(wrapper.ScreenWidth, wrapper.ScreenHeight);
            for (int i = 0; i < wrapper.ScreenHeight; i++)
            {
                for (int j = 0; j < wrapper.ScreenWidth; j++)
                {
                    bkg.SetPixel(j, i, i % 2 == 0 ? System.Drawing.Color.Black : System.Drawing.Color.White);
                }
            }
            if (timerTick >= 60)
            {
                backgroundIndex++;
                timerTick = 0;
            }
            return bkg;
        }
        private System.Drawing.Bitmap MonoBackgroundTest2()
        {
            System.Drawing.Bitmap bkg = new System.Drawing.Bitmap(wrapper.ScreenWidth, wrapper.ScreenHeight);
            for (int i = 0; i < wrapper.ScreenHeight; i++)
            {
                for (int j = 0; j < wrapper.ScreenWidth; j++)
                {
                    bkg.SetPixel(j, i, i % 2 == 1 ? System.Drawing.Color.Black : System.Drawing.Color.White);
                }
            }
            if (timerTick >= 60)
            {
                backgroundIndex++;
                timerTick = 0;
            }
            return bkg;
        }
        private System.Drawing.Bitmap MonoBackgroundTest3()
        {
            System.Drawing.Bitmap bkg = new System.Drawing.Bitmap(wrapper.ScreenWidth, wrapper.ScreenHeight);
            for (int i = 0; i < wrapper.ScreenHeight; i++)
            {
                for (int j = 0; j < wrapper.ScreenWidth; j++)
                {
                    bkg.SetPixel(j, i, (i + j) % 2 == 0 ? System.Drawing.Color.Black : System.Drawing.Color.White);
                }
            }
            if (timerTick >= 60)
            {
                backgroundIndex++;
                timerTick = 0;
            }
            return bkg;
        }
        private System.Drawing.Bitmap MonoBackgroundTest4()
        {
            System.Drawing.Bitmap bkg = new System.Drawing.Bitmap(wrapper.ScreenWidth, wrapper.ScreenHeight);
            for (int i = 0; i < wrapper.ScreenHeight; i++)
            {
                for (int j = 0; j < wrapper.ScreenWidth; j++)
                {
                    bkg.SetPixel(j, i, j % 2 == 0 ? System.Drawing.Color.Black : System.Drawing.Color.White);
                }
            }
            if (timerTick >= 60)
            {
                backgroundIndex++;
                timerTick = 0;
            }
            return bkg;
        }
        private System.Drawing.Bitmap MonoBackgroundTest5()
        {
            System.Drawing.Bitmap bkg = new System.Drawing.Bitmap(wrapper.ScreenWidth, wrapper.ScreenHeight);
            for (int i = 0; i < wrapper.ScreenHeight; i++)
            {
                for (int j = 0; j < wrapper.ScreenWidth; j++)
                {
                    bkg.SetPixel(j, i, j % 2 == 1 ? System.Drawing.Color.Black : System.Drawing.Color.White);
                }
            }
            if (timerTick >= 60)
            {
                backgroundIndex++;
                timerTick = 0;
            }
            return bkg;
        }
        private System.Drawing.Bitmap MonoBackgroundTest6()
        {
            System.Drawing.Bitmap bkg = new System.Drawing.Bitmap(wrapper.ScreenWidth, wrapper.ScreenHeight);
            for (int i = 0; i < wrapper.ScreenSize; i++)
            {
                bkg.SetPixel(i % wrapper.ScreenWidth, i / wrapper.ScreenWidth, (i % wrapper.ScreenWidth) == runningDot ? System.Drawing.Color.Black : System.Drawing.Color.White);
            }
            runningDot = runningDot >= wrapper.ScreenWidth ? 0 : runningDot + 1;
            //((LogitechLCDWrapper.MonoLCDScreen)wrapper).DisplayText(runningDot.ToString(), 1);
            if (runningDot == 0)
            {
                backgroundIndex++;
            }
            return bkg;
        }
        #endregion
        #region Text demo
        int textDemoX = 0, textDemoY = 0, textDuration = 2, textCurrentDuration = 0;
        int textDemoXMultiply = 1, textDemoYMultiply = 1;
        string demoText = "Demo TeXt!!";
        System.Drawing.FontFamily selectedFont;
        private void MonoTextDemo()
        {
            if (wrapper != null)
            {
                if (textCurrentDuration == 0)
                {
                    StartStopTimer();
                    wrapper.ClearBackground();
                    cbxFontSelection.Dispatcher.Invoke(new Action(() => selectedFont = (System.Drawing.FontFamily)cbxFontSelection.SelectedItem));
                    System.Drawing.Font font = new System.Drawing.Font(selectedFont, 10);

                    wrapper.BeginDrawing();
                    var gd = wrapper.GraphicDevice;
                    gd.DrawString(demoText, font, System.Drawing.Brushes.Red , textDemoX, textDemoY);
                    System.Drawing.SizeF stringSize = gd.MeasureString(demoText, font);
                    wrapper.EndDrawing();

                    textDemoXMultiply = textDemoX + 1 + stringSize.Width > wrapper.ScreenWidth ? -1 :
                        (textDemoX + 1 <= 0 ? 1 : textDemoXMultiply);
                    textDemoYMultiply = textDemoY + 1 + stringSize.Height > wrapper.ScreenHeight ? -1 :
                        textDemoY + 1 <= 0 ? 1 : textDemoYMultiply;

                    textDemoX += 1 * textDemoXMultiply;
                    textDemoY += 1 * textDemoYMultiply;
                    StartStopTimer();
                }
                textCurrentDuration = textCurrentDuration + 1 >= textDuration ? 0 : textCurrentDuration + 1;
            }
        }
        private void SetText(string text)
        {
            tbxDemoText.Dispatcher.Invoke(new Action(() => tbxDemoText.Text = text));
            tbxDemoTextColor.Dispatcher.Invoke(new Action(() => tbxDemoText.Text = text));
        }
        private void tbxDemoText_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox t = (TextBox)sender;
            demoText = t.Text;
        }
        private void cbxFontSelection_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

            SetText((e.AddedItems[0] as System.Drawing.FontFamily).Name);
        }
        #endregion
        #endregion

        private void btnCercle_Click(object sender, RoutedEventArgs e)
        {
            if (wrapper != null && wrapper is LogitechLCDWrapper.MonoLCDScreen)
            {
                wrapper.BeginDrawing();
                ((LogitechLCDWrapper.MonoLCDScreen)wrapper).GraphicDevice.DrawEllipse(System.Drawing.Pens.Black, 80, 21, 10, 10);
                wrapper.EndDrawing();
            }
            else if( wrapper != null)
            {
                wrapper.BeginDrawing();
                ((LogitechLCDWrapper.ColorLCDScreen)wrapper).GraphicDevice.FillEllipse(System.Drawing.Pens.Blue.Brush, 80, 21, 100, 100);
                wrapper.EndDrawing();
            }
        }

        private void btnImage_Click(object sender, RoutedEventArgs e)
        {
            if (wrapper != null)
            {
                Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
                ofd.AddExtension = true;
                ofd.CheckFileExists = true;
                ofd.CheckPathExists = true;
                ofd.DefaultExt = "bmp";
                ofd.Filter = "Tous les fichiers|*.*";
                ofd.Multiselect = false;
                ofd.Title = "Choisissez un fichier à charger";
                if (ofd.ShowDialog() == true)
                {
                    System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(ofd.FileName);
                    if (wrapper is LogitechLCDWrapper.MonoLCDScreen)
                    {
                        ((LogitechLCDWrapper.MonoLCDScreen)wrapper).DrawImage(bmp);
                    }
                    else
                    {
                        ((LogitechLCDWrapper.ColorLCDScreen)wrapper).DrawImage(bmp);
                    }
                }
            }
        }

        private void btnClearScreen_Click(object sender, RoutedEventArgs e)
        {
            if (wrapper != null )
            {
                wrapper.ClearBackground();
            }
        }

        private void screenRectangleColor_MouseMove(object sender, MouseEventArgs e)
        {
            if (wrapper != null)
            {
                var pos = e.GetPosition(screenRectangleColor);
                wrapper.BeginDrawing();
                ((LogitechLCDWrapper.ColorLCDScreen)wrapper).SetPixel((int)pos.X, (int)pos.Y, System.Drawing.Color.Red);
                wrapper.EndDrawing();
            }
        }

    }
}
